﻿#region License
/***
 * Copyright © 2018-2020, 张强 (943620963@qq.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * without warranties or conditions of any kind, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#endregion

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.Specialized;
using Quartz;
using Quartz.Impl;
using Quartz.Impl.Triggers;
using Quartz.Logging;
/****************************
* [Author] 张强
* [Date] 2018-11-23
* [Describe] Quartz作业调度工具类
* **************************/
namespace ZqUtils.Core.Helpers
{
    /// <summary>
    /// Quartz作业调度工具类
    /// </summary>
    public class QuartzHelper
    {
        #region StdSchedulerFactory
        /// <summary>
        /// 调度工厂
        /// </summary>
        private static ISchedulerFactory schedulerFactory;
        #endregion

        #region QuartzHelper
        /// <summary>
        /// 静态构造函数
        /// </summary>
        static QuartzHelper()
        {
            //设置LibLog日志驱动，用于记录Quartz内部日志（可以使用其他日志框架如：log4net、nlog等）
            LogProvider.SetCurrentLogProvider(new LibLogProvider());

            #region 初始化调度工厂
            //初始化参数
            var props = new NameValueCollection
            {
                /***
                 * misfireThreshold是用来设置调度引擎对触发器超时的忍耐时间，简单来说misfireThreshold=60000(单位毫秒)默认值。
                 * 那么它的意思说当一个触发器超时时间如果大于misfireThreshold的值 就认为这个触发器真正的超时(也叫Misfires)。
                 * 如果一个触发器超时时间 小于misfireThreshold的值， 那么调度引擎则不认为触发器超时。也就是说调度引擎可以忍受这个超时的时间。
                 */
                ["quartz.jobStore.misfireThreshold"] = "100"
            };

            //实例名称
            var schedulerName = ConfigHelper.GetAppSettings("QuartzNet:SchedulerName", "");
            if (!string.IsNullOrEmpty(schedulerName))
            {
                props["quartz.scheduler.instanceName"] = schedulerName;
            }

            //时区转换插件
            var timeZoneConverterPlugin = ConfigHelper.GetAppSettings("QuartzNet:TimeZoneConverterPlugin", "");
            if (!string.IsNullOrEmpty(timeZoneConverterPlugin))
            {
                //props["quartz.plugin.timeZoneConverter.type"]="Quartz.Plugin.TimeZoneConverter.TimeZoneConverterPlugin, Quartz.Plugins.TimeZoneConverter";
                props["quartz.plugin.timeZoneConverter.type"] = timeZoneConverterPlugin;
            }

            //是否启用持久化
            var isPersistence = ConfigHelper.GetAppSettings("QuartzNet:EnablePersistence", false);
            if (isPersistence)
            {
                //存储类型
                props["quartz.jobStore.type"] = ConfigHelper.GetAppSettings("QuartzNet:PersistenceType", "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz");
                //序列化类型
                props["quartz.serializer.type"] = ConfigHelper.GetAppSettings("QuartzNet:SerializerType", "json");
                //表明前缀
                props["quartz.jobStore.tablePrefix"] = ConfigHelper.GetAppSettings("QuartzNet:TablePrefix", "Quartz_");
                //驱动类型
                props["quartz.jobStore.driverDelegateType"] = ConfigHelper.GetAppSettings("QuartzNet:DriverDelegateType", "Quartz.Impl.AdoJobStore.MySQLDelegate, Quartz");
                //数据源名称
                var dataSource = ConfigHelper.GetAppSettings("QuartzNet:DataSource", "QuartzDataSource");
                props["quartz.jobStore.dataSource"] = dataSource;
                //连接字符串
                props[$"quartz.dataSource.{dataSource}.connectionString"] = ConfigHelper.GetAppSettings<string>("QuartzNet:ConnectionString");
                //sqlserver版本
                props[$"quartz.dataSource.{dataSource}.provider"] = ConfigHelper.GetAppSettings("QuartzNet:Provider", "MySql");
                //最大链接数
                props["quartz.dataSource.myDS.maxConnections"] = ConfigHelper.GetAppSettings("QuartzNet:MaxConnections", "20");
                //Configuring AdoJobStore to use strings as JobDataMap values (recommended)
                props["quartz.jobStore.useProperties"] = ConfigHelper.GetAppSettings("QuartzNet:UseProperties", "true");
                //是否集群
                props["quartz.jobStore.clustered"] = ConfigHelper.GetAppSettings("QuartzNet:Clustered", "true");
                //集群id，要保证唯一，设为AUTO
                props["quartz.scheduler.instanceId"] = ConfigHelper.GetAppSettings("QuartzNet:InstanceId", "AUTO");
                //并发线程数
                props["quartz.threadPool.threadCount"] = ConfigHelper.GetAppSettings("QuartzNet:ThreadCount", "20");
            }

            //实例化工厂
            schedulerFactory = new StdSchedulerFactory(props);
            #endregion
        }
        #endregion

        #region SetStdSchedulerFactoryProps
        /// <summary>
        /// 自定义调度工厂参数
        /// </summary>
        /// <param name="props">参数集</param>
        public static void SetStdSchedulerFactoryProps(NameValueCollection props)
        {
            if (props == null)
                throw new ArgumentException("参数不能为空！");
            if (string.IsNullOrEmpty(props["quartz.jobStore.misfireThreshold"]))
                props["quartz.jobStore.misfireThreshold"] = "100";
            schedulerFactory = new StdSchedulerFactory(props);
        }
        #endregion

        #region Scheduler
        /// <summary>
        /// 获取调度器，会根据配置调度名称获取，没有配置名称获取默认调度
        /// </summary>
        /// <returns></returns>
        public static async Task<IScheduler> GetSchedulerAsync()
        {
            return await schedulerFactory.GetScheduler();
        }
        #endregion

        #region Job
        #region GetJobAsync
        /// <summary>
        /// 获取一个任务
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task<IJobDetail> GetJobAsync<T>() where T : IJob
        {
            return await GetJobAsync(typeof(T));
        }

        /// <summary>
        /// 获取一个任务
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task<IJobDetail> GetJobAsync(Type type)
        {
            return await GetJobAsync($"{type.Name}_Job", $"{type.Name}_JobGroup");
        }

        /// <summary>
        /// 获取一个任务
        /// </summary>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <returns></returns>
        public static async Task<IJobDetail> GetJobAsync(string jobName, string jobGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            return await sched.GetJobDetail(new JobKey(jobName, jobGroupName));
        }
        #endregion

        #region AddJobAsync
        /// <summary>
        /// 添加一个定时任务，注意：一个Job可以对应多个Trigger，但一个Trigger只能对应一个Job
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <param name="data">自定义数据</param>
        /// <returns></returns>
        public static async Task AddJobAsync<T>(string cron, Dictionary<string, object> data = null) where T : IJob
        {
            await AddJobAsync(typeof(T), cron, data);
        }

        /// <summary>
        /// 添加一个定时任务，注意：一个Job可以对应多个Trigger，但一个Trigger只能对应一个Job
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <param name="data">自定义数据</param>
        /// <returns></returns>
        public static async Task AddJobAsync(Type type, string cron, Dictionary<string, object> data = null)
        {
            await AddJobAsync(type, $"{type.Name}_Job", $"{type.Name}_JobGroup", $"{type.Name}_Trigger", $"{type.Name}_TriggerGroup", cron, data);
        }

        /// <summary>
        /// 添加一个定时任务，注意：一个Job可以对应多个Trigger，但一个Trigger只能对应一个Job
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <param name="data">自定义数据</param>
        /// <returns></returns>
        public static async Task AddJobAsync<T>(string jobName, string jobGroupName, string triggerName, string triggerGroupName, string cron, Dictionary<string, object> data = null) where T : IJob
        {
            await AddJobAsync(typeof(T), jobName, jobGroupName, triggerName, triggerGroupName, cron, data);
        }

        /// <summary>
        /// 添加一个定时任务，注意：一个Job可以对应多个Trigger，但一个Trigger只能对应一个Job
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <param name="data">自定义数据</param>
        /// <returns></returns>
        public static async Task AddJobAsync(Type type, string jobName, string jobGroupName, string triggerName, string triggerGroupName, string cron, Dictionary<string, object> data = null)
        {
            var sched = await schedulerFactory.GetScheduler();
            //任务名，任务组，任务执行类
            var jobDetail = JobBuilder.Create(type).WithIdentity(jobName, jobGroupName).Build();
            //注入自定义数据
            if (data?.Count > 0)
            {
                foreach (var item in data)
                {
                    jobDetail.JobDataMap.Add(item);
                }
            }
            //触发器  
            var trigger = TriggerBuilder
                            .Create()
                            .WithIdentity(new TriggerKey(triggerName, triggerGroupName))
                            .WithSchedule(CronScheduleBuilder.CronSchedule(cron).WithMisfireHandlingInstructionDoNothing())//对错过的内容不再执行
                            .Build();
            //调度容器设置JobDetail和Trigger
            await sched.ScheduleJob(jobDetail, trigger);
            //启动  
            await sched.Start();
        }
        #endregion

        #region RemoveJobAsync
        /// <summary>
        /// 移除一个任务
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task<bool> RemoveJobAsync<T>() where T : IJob
        {
            return await RemoveJobAsync(typeof(T));
        }

        /// <summary>
        /// 移除一个任务
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task<bool> RemoveJobAsync(Type type)
        {
            return await RemoveJobAsync($"{type.Name}_Job", $"{type.Name}_JobGroup");
        }

        /// <summary>
        /// 移除一个任务
        /// </summary>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <returns></returns>
        public static async Task<bool> RemoveJobAsync(string jobName, string jobGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            return await sched.DeleteJob(new JobKey(jobName, jobGroupName));
        }

        /// <summary>
        /// 移除多个任务
        /// </summary>
        /// <param name="jobs">任务名和任务组名字典集合</param>
        /// <returns></returns>
        public static async Task<bool> RemoveJobsAsync(Dictionary<string, string> jobs)
        {
            var sched = await schedulerFactory.GetScheduler();
            return await sched.DeleteJobs(jobs.Select(o => new JobKey(o.Key, o.Value)).ToList());
        }
        #endregion

        #region UpdateJobAsync
        /// <summary>
        /// 更新一个任务的触发时间
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <returns></returns>
        public static async Task UpdateJobAsync<T>(string cron) where T : IJob
        {
            await UpdateJobAsync(typeof(T), cron);
        }

        /// <summary>
        /// 更新一个任务的触发时间
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <returns></returns>
        public static async Task UpdateJobAsync(Type type, string cron)
        {
            await UpdateJobAsync($"{type.Name}_Job", $"{type.Name}_JobGroup", $"{type.Name}_Trigger", $"{type.Name}_TriggerGroup", cron);
        }

        /// <summary>
        /// 更新一个任务的触发时间
        /// </summary>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <param name="triggerName">新触发器名</param>
        /// <param name="triggerGroupName">新触发器组名</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <returns></returns>
        public static async Task UpdateJobAsync(string jobName, string jobGroupName, string triggerName, string triggerGroupName, string cron)
        {
            var sched = await schedulerFactory.GetScheduler();
            var trigger = (await sched.GetTriggersOfJob(new JobKey(jobName, jobGroupName))).FirstOrDefault();
            if (trigger != null)
            {
                var ct = (CronTriggerImpl)trigger;
                if (!ct.CronExpressionString.Equals(cron, StringComparison.InvariantCultureIgnoreCase))
                {
                    // 触发器  
                    var triggerNew = TriggerBuilder
                                        .Create()
                                        .WithIdentity(triggerName, triggerGroupName)
                                        .WithSchedule(CronScheduleBuilder.CronSchedule(cron).WithMisfireHandlingInstructionDoNothing())
                                        .Build();
                    await sched.RescheduleJob(trigger.Key, triggerNew);
                    // 启动  
                    await sched.Start();
                }
            }
        }
        #endregion

        #region PauseJobAsync
        /// <summary>
        /// 暂停一个任务
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task PauseJobAsync<T>() where T : IJob
        {
            await PauseJobAsync(typeof(T));
        }

        /// <summary>
        /// 暂停一个任务
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task PauseJobAsync(Type type)
        {
            await PauseJobAsync($"{type.Name}_Job", $"{type.Name}_JobGroup");
        }

        /// <summary>
        /// 暂停一个任务
        /// </summary>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <returns></returns>
        public static async Task PauseJobAsync(string jobName, string jobGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            await sched.PauseJob(new JobKey(jobName, jobGroupName));
        }
        #endregion

        #region ResumeJobAsync
        /// <summary>
        /// 恢复一个任务
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task ResumeJobAsync<T>() where T : IJob
        {
            await ResumeJobAsync(typeof(T));
        }

        /// <summary>
        /// 恢复一个任务
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task ResumeJobAsync(Type type)
        {
            await ResumeJobAsync($"{type.Name}_Job", $"{type.Name}_JobGroup");
        }

        /// <summary>
        /// 恢复一个任务
        /// </summary>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <returns></returns>
        public static async Task ResumeJobAsync(string jobName, string jobGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            await sched.ResumeJob(new JobKey(jobName, jobGroupName));
        }
        #endregion

        #region ShutdownAllAsync
        /// <summary>
        /// 关闭所有任务，并清除所有资源
        /// </summary>
        /// <returns></returns>
        public static async Task ShutdownAllAsync()
        {
            var sched = await schedulerFactory.GetScheduler();
            await sched.Shutdown();
        }
        #endregion

        #region PauseAllAsync
        /// <summary>
        /// 暂停所有任务
        /// </summary>
        /// <returns></returns>
        public static async Task PauseAllAsync()
        {
            var sched = await schedulerFactory.GetScheduler();
            await sched.PauseAll();
        }
        #endregion

        #region ResumeAllAsync
        /// <summary>
        /// 恢复所有任务
        /// </summary>
        /// <returns></returns>
        public static async Task ResumeAllAsync()
        {
            var sched = await schedulerFactory.GetScheduler();
            await sched.ResumeAll();
        }
        #endregion
        #endregion

        #region Trigger
        #region GetTriggerStateAsync
        /// <summary>
        /// 获取指定触发器的状态
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task<TriggerState> GetTriggerStateAsync<T>() where T : IJob
        {
            return await GetTriggerStateAsync(typeof(T));
        }

        /// <summary>
        /// 获取指定触发器的状态
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task<TriggerState> GetTriggerStateAsync(Type type)
        {
            return await GetTriggerStateAsync($"{type.Name}_Trigger", $"{type.Name}_TriggerGroup");
        }

        /// <summary>
        /// 获取指定触发器的状态
        /// </summary>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <returns></returns>
        public static async Task<TriggerState> GetTriggerStateAsync(string triggerName, string triggerGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            return await sched.GetTriggerState(new TriggerKey(triggerName, triggerGroupName));
        }

        /// <summary>
        /// 获取指定任务的所有触发器状态
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task<List<TriggerState>> GetTriggerStatesAsync<T>() where T : IJob
        {
            return await GetTriggerStatesAsync(typeof(T));
        }

        /// <summary>
        /// 获取指定任务的所有触发器状态
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task<List<TriggerState>> GetTriggerStatesAsync(Type type)
        {
            return await GetTriggerStatesAsync($"{type.Name}_Job", $"{type.Name}_JobGroup");
        }

        /// <summary>
        /// 获取指定任务的所有触发器状态
        /// </summary>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <returns></returns>
        public static async Task<List<TriggerState>> GetTriggerStatesAsync(string jobName, string jobGroupName)
        {
            var list = new List<TriggerState>();
            var sched = await schedulerFactory.GetScheduler();
            var triggers = await sched.GetTriggersOfJob(new JobKey(jobName, jobGroupName));
            foreach (var trigger in triggers)
            {
                list.Add(await sched.GetTriggerState(trigger.Key));
            }
            return list;
        }
        #endregion

        #region GetTriggerAsync
        /// <summary>
        /// 获取一个触发器
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task<ITrigger> GetTriggerAsync<T>() where T : IJob
        {
            return await GetTriggerAsync(typeof(T));
        }

        /// <summary>
        /// 获取一个触发器
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task<ITrigger> GetTriggerAsync(Type type)
        {
            return await GetTriggerAsync($"{type.Name}_Trigger", $"{type.Name}_TriggerGroup");
        }

        /// <summary>
        /// 获取一个触发器
        /// </summary>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <returns></returns>
        public static async Task<ITrigger> GetTriggerAsync(string triggerName, string triggerGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            return await sched.GetTrigger(new TriggerKey(triggerName, triggerGroupName));
        }

        /// <summary>
        /// 获取指定任务对应的所有触发器
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task<IReadOnlyCollection<ITrigger>> GetTriggersAsync<T>() where T : IJob
        {
            return await GetTriggersAsync(typeof(T));
        }

        /// <summary>
        /// 获取指定任务对应的所有触发器
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task<IReadOnlyCollection<ITrigger>> GetTriggersAsync(Type type)
        {
            return await GetTriggersAsync($"{type.Name}_Job", $"{type.Name}_JobGroup");
        }

        /// <summary>
        /// 获取指定任务对应的所有触发器
        /// </summary>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <returns></returns>
        public static async Task<IReadOnlyCollection<ITrigger>> GetTriggersAsync(string jobName, string jobGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            return await sched.GetTriggersOfJob(new JobKey(jobName, jobGroupName));
        }
        #endregion

        #region AddTriggerAsync
        /// <summary>
        /// 添加一个触发器
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <returns></returns>
        public static async Task AddTriggerAsync<T>(string cron) where T : IJob
        {
            await AddTriggerAsync(typeof(T), cron);
        }

        /// <summary>
        /// 添加一个触发器
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <returns></returns>
        public static async Task AddTriggerAsync(Type type, string cron)
        {
            await AddTriggerAsync(type, null, null, cron);
        }

        /// <summary>
        /// 添加一个触发器
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <returns></returns>
        public static async Task AddTriggerAsync<T>(string triggerName, string triggerGroupName, string cron) where T : IJob
        {
            await AddTriggerAsync(typeof(T), triggerName, triggerGroupName, cron);
        }

        /// <summary>
        /// 添加一个触发器
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <returns></returns>
        public static async Task AddTriggerAsync(Type type, string triggerName, string triggerGroupName, string cron)
        {
            await AddTriggerAsync(type, $"{type.Name}_Job", $"{type.Name}_JobGroup", triggerName, triggerGroupName, cron);
        }

        /// <summary>
        /// 添加一个触发器
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <returns></returns>
        public static async Task AddTriggerAsync<T>(string jobName, string jobGroupName, string triggerName, string triggerGroupName, string cron) where T : IJob
        {
            await AddTriggerAsync(typeof(T), jobName, jobGroupName, triggerName, triggerGroupName, cron);
        }

        /// <summary>
        /// 添加一个触发器
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroupName">任务组名</param>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <param name="cron">时间设置，参考quartz说明文档</param>
        /// <returns></returns>
        public static async Task AddTriggerAsync(Type type, string jobName, string jobGroupName, string triggerName, string triggerGroupName, string cron)
        {
            var sched = await schedulerFactory.GetScheduler();
            var triggers = (await sched.GetTriggersOfJob(new JobKey(jobName, jobGroupName))).ToList();
            if (triggers?.Count > 0)
            {
                //获取原有JobData
                var data = (await sched.GetJobDetail(new JobKey(jobName, jobGroupName))).JobDataMap;
                //删除原有job
                await sched.DeleteJob(new JobKey(jobName, jobGroupName));
                //创建新触发器  
                var triggerBuilder = TriggerBuilder.Create();
                //判断触发器是否为空
                if (!string.IsNullOrEmpty(triggerName) && !string.IsNullOrEmpty(triggerGroupName))
                {
                    triggerBuilder = triggerBuilder.WithIdentity(triggerName, triggerGroupName);
                }
                var triggerNew = triggerBuilder.WithSchedule(CronScheduleBuilder.CronSchedule(cron).WithMisfireHandlingInstructionDoNothing()).Build();
                triggers.Add(triggerNew);
                var jobDetail = JobBuilder.Create(type).WithIdentity(jobName, jobGroupName).Build();
                //重新注入数据
                if (data?.Count > 0)
                {
                    foreach (var item in data)
                    {
                        jobDetail.JobDataMap.Add(item.Key, item.Value);
                    }
                }
                //重新创建job
                await sched.ScheduleJob(jobDetail, triggers, true);
                //启动  
                await sched.Start();
            }
        }
        #endregion

        #region RemoveTriggerAsync
        /// <summary>
        /// 移除一个触发器
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task<bool> RemoveTriggerAsync<T>() where T : IJob
        {
            return await RemoveTriggerAsync(typeof(T));
        }

        /// <summary>
        /// 移除一个触发器
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task<bool> RemoveTriggerAsync(Type type)
        {
            return await RemoveTriggerAsync($"{type.Name}_Trigger", $"{type.Name}_TriggerGroup");
        }

        /// <summary>
        /// 移除一个触发器
        /// </summary>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <returns></returns>
        public static async Task<bool> RemoveTriggerAsync(string triggerName, string triggerGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            return await sched.UnscheduleJob(new TriggerKey(triggerName, triggerGroupName));
        }

        /// <summary>
        /// 移除多个触发器
        /// </summary>
        /// <param name="triggers">触发器名和触发器组名字典集合</param>
        /// <returns></returns>
        public static async Task<bool> RemoveTriggersAsync(Dictionary<string, string> triggers)
        {
            var sched = await schedulerFactory.GetScheduler();
            return await sched.UnscheduleJobs(triggers.Select(o => new TriggerKey(o.Key, o.Value)).ToList());
        }
        #endregion

        #region PauseTriggerAsync
        /// <summary>
        /// 暂停一个触发器
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task PauseTriggerAsync<T>() where T : IJob
        {
            await PauseTriggerAsync(typeof(T));
        }

        /// <summary>
        /// 暂停一个触发器
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task PauseTriggerAsync(Type type)
        {
            await PauseTriggerAsync($"{type.Name}_Trigger", $"{type.Name}_TriggerGroup");
        }

        /// <summary>
        /// 暂停一个触发器
        /// </summary>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <returns></returns>
        public static async Task PauseTriggerAsync(string triggerName, string triggerGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            await sched.PauseTrigger(new TriggerKey(triggerName, triggerGroupName));
        }
        #endregion

        #region ResumeTriggerAsync
        /// <summary>
        /// 恢复一个触发器
        /// </summary>
        /// <typeparam name="T">IJob实现类</typeparam>
        /// <returns></returns>
        public static async Task ResumeTriggerAsync<T>() where T : IJob
        {
            await ResumeTriggerAsync(typeof(T));
        }

        /// <summary>
        /// 恢复一个触发器
        /// </summary>
        /// <param name="type">IJob实现类Type</param>
        /// <returns></returns>
        public static async Task ResumeTriggerAsync(Type type)
        {
            await ResumeTriggerAsync($"{type.Name}_Trigger", $"{type.Name}_TriggerGroup");
        }

        /// <summary>
        /// 恢复一个触发器
        /// </summary>
        /// <param name="triggerName">触发器名</param>
        /// <param name="triggerGroupName">触发器组名</param>
        /// <returns></returns>
        public static async Task ResumeTriggerAsync(string triggerName, string triggerGroupName)
        {
            var sched = await schedulerFactory.GetScheduler();
            await sched.ResumeTrigger(new TriggerKey(triggerName, triggerGroupName));
        }
        #endregion
        #endregion
    }

    /// <summary>
    /// 自定义实现LibLog的ILogProvider接口
    /// </summary>
    public class LibLogProvider : ILogProvider
    {
        /// <summary>
        /// GetLogger
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public Logger GetLogger(string name)
        {
            return (level, func, exception, parameters) =>
            {
                if (level == LogLevel.Info)
                {
                    LogHelper.Info(func?.Invoke(), parameters);
                }
                else if (level == LogLevel.Error)
                {
                    LogHelper.Error(exception, func?.Invoke(), parameters);
                }
                return true;
            };
        }

        /// <summary>
        /// OpenMappedContext(未实现)
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public IDisposable OpenMappedContext(string key, string value)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// OpenNestedContext(未实现)
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public IDisposable OpenNestedContext(string message)
        {
            throw new NotImplementedException();
        }
    }
}
